// Copyright 2018 The Feed Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.android.libraries.feed.piet.ui;

import android.content.Context;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.RoundRectShape;
import com.google.android.libraries.feed.common.ui.LayoutUtils;
import com.google.search.now.ui.piet.StylesProto.Borders;
import com.google.search.now.ui.piet.StylesProto.Borders.Edges;

/**
 * Shape used to draw borders. Uses offsets to push the border out of the drawing bounds if it is
 * not specified.
 */
public class BorderDrawable extends ShapeDrawable {
  private final int offsetToHideLeft;
  private final int offsetToHideRight;
  private final int offsetToHideTop;
  private final int offsetToHideBottom;

  // Doesn't like calls to getPaint()
  @SuppressWarnings("initialization")
  public BorderDrawable(Context context, Borders borders, float[] cornerRadii) {
    super(new RoundRectShape(cornerRadii, null, null));

    int borderWidth = (int) LayoutUtils.dpToPx(borders.getWidth(), context);

    // Calculate the offsets which push the border outside the view, making it invisible
    int bitmask = borders.getBitmask();
    if (bitmask == 0 || bitmask == 15) {
      // All borders are visible
      offsetToHideLeft = 0;
      offsetToHideRight = 0;
      offsetToHideTop = 0;
      offsetToHideBottom = 0;
    } else {
      boolean isLtR = !LayoutUtils.isDefaultLocaleRtl();
      int leftEdge = isLtR ? Edges.START.getNumber() : Edges.END.getNumber();
      int rightEdge = isLtR ? Edges.END.getNumber() : Edges.START.getNumber();
      boolean hasLeftBorder = (bitmask & leftEdge) != 0;
      boolean hasRightBorder = (bitmask & rightEdge) != 0;
      boolean hasTopBorder = (bitmask & Edges.TOP.getNumber()) != 0;
      boolean hasBottomBorder = (bitmask & Edges.BOTTOM.getNumber()) != 0;
      offsetToHideLeft = hasLeftBorder ? 0 : -borderWidth;
      offsetToHideRight = hasRightBorder ? 0 : borderWidth;
      offsetToHideTop = hasTopBorder ? 0 : -borderWidth;
      offsetToHideBottom = hasBottomBorder ? 0 : borderWidth;
    }
    getPaint().setStyle(Paint.Style.STROKE);
    // Multiply the width by two - the centerline of the stroke will be the edge of the view, so
    // half of the stroke will be outside the view. In order for the visible portion to have the
    // correct width, the full stroke needs to be twice as wide.
    // For rounded corners, this relies on the containing FrameLayout to crop the outside half of
    // the rounded border; otherwise, the border would get thicker on the corners.
    getPaint().setStrokeWidth(borderWidth * 2);
    getPaint().setColor(borders.getColor());
  }

  @Override
  public void setBounds(int left, int top, int right, int bottom) {
    super.setBounds(
        left + offsetToHideLeft,
        top + offsetToHideTop,
        right + offsetToHideRight,
        bottom + offsetToHideBottom);
  }

  @Override
  public void setBounds(Rect bounds) {
    setBounds(bounds.left, bounds.top, bounds.right, bounds.bottom);
  }
}
